﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.Threading;
using System.Runtime.Remoting.Messaging;
using System.IO;
using System.Diagnostics;

using WcfCore;
using WcfServices.Proxies;

namespace WcfServices
{
#if (SINGLE)
	[ServiceContract(Namespace = "http://Wcf/Services")]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
	public class WcfService :
#elif (PERSESSION)
	[ServiceContract(Namespace = "http://Wcf/Services", SessionMode = SessionMode.Required)]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
	public class WcfService :
#elif (PERCALL)
	[ServiceContract(Namespace = "http://Wcf/Services")]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
	public class WcfService :
#endif
		MarshalByRefObject, IWcfServiceContract
	{
		private static readonly WcfException _wcfException = new WcfException();
		public WcfException WcfException
		{
			get
			{
				return _wcfException;
			}
		}

		private static WcfTestInput _input;
		public WcfTestInput Input
		{
			get
			{
				return WcfService._input;
			}
			set
			{
				WcfService._input = value;
			}
		}

		private byte[] _receivedData;
		public byte[] ReceivedData
		{
			get
			{
				return _receivedData;
			}
			set
			{
				_receivedData = value;
			}
		}

		private byte[] _receivedStreamData;
		public byte[] ReceivedStreamData
		{
			get
			{
				return _receivedStreamData;
			}
			set
			{
				_receivedStreamData = value;
			}
		}

		private SimpleContainer _simpleContainer;
		public SimpleContainer SimpleContainer
		{
			get
			{
				return _simpleContainer;
			}
			set
			{
				_simpleContainer = value;
			}
		}

		private AdvancedContainer _advancedContainer;
		public AdvancedContainer AdvancedContainer
		{
			get
			{
				return _advancedContainer;
			}
			set
			{
				_advancedContainer = value;
			}
		}

		private string _receivedText;
		public string ReceivedText
		{
			get
			{
				return _receivedText;
			}
			set
			{
				_receivedText = value;
			}
		}

		private SimpleTextContainer _simpleTextContainer;
		public SimpleTextContainer SimpleTextContainer
		{
			get
			{
				return _simpleTextContainer;
			}
			set
			{
				_simpleTextContainer = value;
			}
		}

		private AdvancedTextContainer _advancedTextContainer;
		public AdvancedTextContainer AdvancedTextContainer
		{
			get
			{
				return _advancedTextContainer;
			}
			set
			{
				_advancedTextContainer = value;
			}
		}

		private static WcfOneWayLatencyTestServiceProxy _oneWayLatencyTestServiceProxy;
		public WcfOneWayLatencyTestServiceProxy OneWayLatencyTestServiceProxy
		{
			get
			{
				if (WcfService._oneWayLatencyTestServiceProxy == null)
				{
					WcfService._oneWayLatencyTestServiceProxy = new WcfOneWayLatencyTestServiceProxy();
				}
				return WcfService._oneWayLatencyTestServiceProxy;
			}
		}

#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void Initialize(WcfTestInput input)
		{
			this.Input = input;
			if (this.Input.ReceiveDataMethod.Equals(ReceiveDataMethods.ReceiveStream))
			{
				this.ReceivedStreamData = new byte[this.Input.DataSize];
			}

			WcfLogger.Log(string.Format("Current Process Id: {0}; Current AppDomain Id: {1}.", Process.GetCurrentProcess().Id, AppDomain.CurrentDomain.Id));
			WcfLogger.Log(string.Format("Service Receiving: {0}", this.Input.DisplayName));

#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveData(byte[] data)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.ReceivedData = data;
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveSC(SimpleContainer container)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.SimpleContainer = container;
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveAC(AdvancedContainer container)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.AdvancedContainer = container;
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveStream(Stream data)
		{
			int bytesRead = 0;
			while (bytesRead < this.Input.DataSize)
			{
				bytesRead += data.Read(this.ReceivedStreamData, bytesRead, this.Input.DataSize - bytesRead);
			}
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveText(string text)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.ReceivedText = text;
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveSTC(SimpleTextContainer container)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.SimpleTextContainer = container;
		}

#if (PORDCSF)
		[PreserveObjectReferencesDataContractSerializerFormat]
#elif (NDCSF)
		[NetDataContractSerializerFormat]
#elif (XMLSF)
		[XmlSerializerFormat]
#endif
#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveATC(AdvancedTextContainer container)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.AdvancedTextContainer = container;
		}

#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void ReceiveDataThrowException(byte[] data)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.ReceivedData = data;
			throw this.WcfException;
		}

#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
		[TransactionFlow(TransactionFlowOption.Allowed)]
#endif
		public void ReceiveDataTransactional(byte[] data)
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
			this.ReceivedData = data;
		}

#if (ISONEWAY)
		[OperationContract(IsOneWay = true)]
		[OneWay]
#else
		[OperationContract]
#endif
		public void TerminateSession()
		{
#if (ISONEWAY)
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
#endif
		}

		[OperationContract(IsOneWay = true)]
		public void OneWayLatencyTest()
		{
			OneWayLatencyTestServiceProxy.OneWayLatencyTest();
		}
	}
}
